﻿module Lexer

open System
open Word
open Num
open Token
open System.Text
open System.Collections.Generic
open CharExtension
open System.IO
///用fsharp写不下去了 2011-04-13 18:32
let IsLetter (c:char) =
    c>'a'&&c<'z'|| c>'A'&&c<'Z'
let IsNum (c:char) =
    c>'0'&&c<'9'
let IsLetterOrNum (c:char)=
    (IsLetter c) || (IsNum c)

type Lexer(sourceString:string)=
        let  line =ref 1 

        ///关键字集合
        let words = new Dictionary<string,Word>()
        ///添加关键字方法
        let reserve(w:Word ) = words.Add( w.Lexeme,w)
        do  reserve(new Word(Tag.TRUE,"true"))
        do reserve(new Word(Tag.FALSE,"false"))
        ///利用StringReader方便分析字符串
        let strReader = new StringReader(sourceString)
        let  getPeek()=char (strReader.Read())

        let mutable peek = ' '
        let rec skipBlankReturnPst()=
                peek <- getPeek()
                match peek with
                | ' ' | '\t' -> skipBlankReturnPst()
                | '\n' -> 
                        incr line
                        skipBlankReturnPst()
                | _ -> ()

        /// 从当前pst获取str的一个字符，并转换成int，不保证数组是否越界
        let tryGetDigit()=
                let peek = getPeek()
                if IsNum peek then
                        Some(peek)
                else None

        let tryReturnNum()=
                let mutable digit = tryGetDigit()
                match digit with
                | None ->
                                None
                | Some(pk) -> 
                                let rec Counting(sum:int)=
                                        let nextDigit =tryGetDigit()
                                        match nextDigit with
                                        | Some(pk) ->
                                                let newSum = sum*10+pk.ToDigit()
                                                Counting(newSum)
                                        | None  ->
                                                sum
                                Some(Counting(pk.ToDigit()))
//
//        let tryGetChar()=
//                let peek = getPeek()
//                if IsLetter peek then
//                        Some(peek)
//                else None
//        let tryReturnWord () =     
//                let sb =new StringBuilder()
//                let rec build(sb:StringBuilder) =
//                        let one = tryGetChar()
//                        match one with
//                        | None

//        let printNUM (v:int) =
//                printf "<NUM,%d>" v
//        let printWORD (w:Word)=
//                printf "<WORD,%s>" w.Lexeme
//        member this.Scan(input:string) =
//                let input =BasicIO.GetInputString
//                let pst = ref 0
//                pst := skipBlankReturnPst(input)
//
//                while !pst < input.Length do
//                        let pstAndValue= tryReturnNum(!pst,input)
//                        if pstAndValue.IsSome then //包含数字
//                        let (newPst,num) = pstAndValue.Value
//                        pst:=newPst
//                        printNUM num
//                        else  //是keyword
//                                let (newPst,keyword )= ReturnWord(!pst,input)
//                                pst:=newPst
//                                if words.ContainsKey keyword then
//                                printWORD words.[keyword]
//                                else
//                                let w = Word(Tag.ID,keyword)
//                                words.Add(keyword, w)
//                                printWORD w
//
//
//
//        
//           
//
//
                            
            
  
    
